<template>
   <div class="app-container">
    <!--1.查询模块 -->
    <el-form :inline="true" size="small">
      <!-- 表单元素 -->
      <el-form-item >
         <el-input v-model="tempSearchObj.username" placeholder="用户名" />
      </el-form-item>
      <!-- 查询与情况的按钮 -->
      <el-button type="primary" icon="el-icon-search" size="small" @click="search">查询</el-button>
      <el-button type="default"  size="small" @click="resetSearch">清空</el-button>
    </el-form>

    <!--2.添加用户 -->
    <div style="margin-bottom: 20px">
      <!-- 添加与批量添加按钮 -->
      <el-button type="primary" size="small" @click="showAddUser">添 加</el-button>
      <el-button type="danger"  :disabled="selectedIds.length===0" size="small" @click="revomveUsers"
        >批量删除</el-button>
    </div>

    <!-- 3.table表格：展示用户信息的地方 -->
    <!--  @current-change="handleCurrentChange" 管理选中时触发的事件-->
    <el-table
      size="small"
      border
      stripe
      v-loading="listLoading"
      :data="users"
      @selection-change="handleSelectionChange">

      <el-table-column
        type="selection"
        width="55" 
        align="center"
        />

      <el-table-column
        type="index"
        label="序号"
        width="80"
        align="center"
      />
      <el-table-column prop="username" label="用户名" width="150" />
      <el-table-column prop="nickName" label="用户昵称" />
      <el-table-column prop="roleName" label="权限列表" />
      
      <el-table-column prop="gmtCreate" label="创建时间" width="180"/>
      <el-table-column prop="gmtModified" label="更新时间" width="180"/>

      <el-table-column label="操作" width="230" align="center">
        <template v-slot:default="{row}">
          <HintButton type="info" size="mini" icon="el-icon-user-solid" title="分配角色"
            @click="showAssignRole(row)"/>
          <HintButton type="primary" size="mini" icon="el-icon-edit" title="修改用户"
            @click="showUpdateUser(row)"/>
          <el-popconfirm :title="`确定删除 ${row.username} 吗?`" @onConfirm="removeUser(row.id)">
            <HintButton style="margin-left:10px" slot="reference" type="danger" size="mini" icon="el-icon-delete" 
              title="删除用户"/>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>

    <!--4.底部分页器 
            当前第几页、总共多少数据、每页展示多少数据、连续的页码数
             @size-change="handleSizeChange" 
             @current-change="handleCurrentChange"
             current-page:代表当前第几页
             total:代表分页器一共需要展示数据条数
             page-size:代表的是每页展示多少条数据
             page-sizes:表示可以设置每一页展示多少条数据
             layout：可以实现分页器的布局
             pager-count：按钮的数量9，连续的页码数7  
     -->
    <el-pagination 
        style="padding: 20px 0; text-align: center;"
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"
        :current-page="currentPage"
        :page-size="limit"
        :page-sizes="[5, 10, 20, 30, 40, 50, 100]"
        layout="prev, pager, next, jumper, ->, sizes, total"
        :total="total"
        :pager-count=5
          >
    </el-pagination>
   
<!-- 5.对话框-->
<!-- a.添加&修改的对话框 -->
    <el-dialog :title="user.id?'修改用户':'添加用户'" :visible.sync="dialogUserVisible"  width="40%" :before-close="cancel"> 
      <!--用户信息表单 -->
      <el-form ref="userForm" :model="user" :rules="userRules" label-width="120px">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="user.username" style="width: 80%;"/>
        </el-form-item>

        <el-form-item label="用户昵称">
          <el-input v-model="user.nickName" style="width: 80%;" />
        </el-form-item>
        <!-- 用户密码自定义校验 -->
        <el-form-item v-if="!user.id" label="用户密码" prop="password">
          <el-input v-model="user.password" style="width: 80%;" />
        </el-form-item>
        <!-- <el-form-item label="确认密码" prop="checkPass">
          <el-input type="password" v-model="user.checkPass" autocomplete="off"></el-input>
        </el-form-item> -->
      </el-form>

      <div slot="footer" class="dialog-footer" >
        <el-button @click="cancel" size="small">取 消</el-button>
        <el-button :loading="loading" type="primary" @click="addOrUpdate" size="small">确 定</el-button>
      </div>
    </el-dialog>


<!-- b.分配角色对话框 -->
   <!-- 关闭前的回调，会暂停 Dialog 的关闭 function(done)，done 用于关闭 Dialog-->
    <el-dialog title="设置角色" :visible.sync="dialogRoleVisible" :before-close="resetRoleData" width="40%">
      <el-form label-width="80px">
        <el-form-item label="用户名">
          <el-input disabled :value="user.username" style="width:95%"></el-input>
        </el-form-item>
         <!-- 多选框 -->
        <el-form-item label="角色列表">          
          <el-checkbox :indeterminate="isIndeterminate" v-model="checkAll" @change="handleCheckAllChange">全选</el-checkbox>
          <div style="margin: 15px 0;"></div>
          <el-checkbox-group v-model="userRoleIds" @change="handleCheckedChange">
            <el-checkbox v-for="role in allRoles" :key="role.id" :label="role.id">{{role.roleName}}</el-checkbox>
          </el-checkbox-group>
        </el-form-item>
      </el-form>
    
      <div slot="footer">
        <el-button :loading="loading" type="primary" @click="SaveAssignRole" size="small">保存</el-button>
        <el-button @click="resetRoleData" size="small">取消</el-button>
      </div>
    </el-dialog>
   </div>
</template>

<script>
// 按需引入lodash当中的深拷贝
import cloneDeep from 'lodash/cloneDeep'

export default {
   name: 'AclUserList',
   data() {
    return {
      currentPage: 1, // 当前页码
      limit: 5, // 每页数量
      total: 0, // 总数量
      listLoading: false, // 是否显示列表加载的提示
      searchObj: { // 包含请求搜索条件数据的对象
        username: ''
      },
      tempSearchObj: { // 收集搜索条件输入的对象
        username: ''
      },
      users: [], // 当前页的用户列表
      selectedIds: [], // 存储所有选择的user的id的数组
 
      user: {}, // 当前要操作的user

      //添加or修改用户信息对话框控制,是否显示角色Dialog
      dialogUserVisible: false,
      //分配角色信息对话框控制
      dialogRoleVisible: false,   

      userRules: { // 用户添加/修改表单的校验规则
        username: [
          { required: true, message: '用户名必须输入' },
          { min: 4, message: '用户名不能小于4位' }
        ],
        password: [
          { required: true, validator:this.validatePassWord }
        ]
      },
      loading: false, // 是否正在提交请求中

      /* 多选框数据 */
      allRoles: [], // 存储所有角色的列表
      userRoleIds: [], // 用户的角色ID的列表
      /* 全选框的多个状态 */
      isIndeterminate: false, //有选中，未全选也没有全不选
      checkAll: false, // 是否全选
    }
   },
   methods:{
     /*current-change事件来管理选中时触发的事件，它会传入currentRow，oldCurrentRow*/ 
      handleSelectionChange(selection){
             this.selectedIds = selection.map((item)=>{
                    return item.id
             })
      },

    /* 批量删除用户信息*/
      revomveUsers(){
        //MessageBox弹框
        this.$confirm('此操作将永久删除该用户, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(async () => {
        await this.$API.user.removeUsers(this.selectedIds)
        this.$message.success('删除成功')
        this.getUsers()
      }).catch(() => {
        this.$message.info('取消删除')
      })
      },
      
    /* 分页器 */
      handleSizeChange(val){
        // console.log(`每页 ${val} 条`);
        // 修改当前页展示数据条数
          this.limit = val
          this.getUsers()
      },
      handleCurrentChange(val){
        // console.log(`当前页: ${val}`);
          this.getUsers(val)
      },

    /* 
    获取用户信息分页列表
    */
        async getUsers (page=1) {
          this.currentPage = page
          //请求搜索条件的对象searchObj,携带query参数，后台进行模糊查询返回数据
          const {limit, searchObj} = this
          //请求后开启加载效果
          this.listLoading = true
          const result = await this.$API.user.getPageList(page, limit, searchObj)
          //响应成功，关闭加载
          this.listLoading = false
          const {items, total} = result.data
          //过滤掉username中的admin,将不等于admin的用户生成新的数组返回
          this.users = items.filter(item => item.username!=='admin')
          // this.users = items
          //问题：返回的总条数total多了1
          this.total = total -1
          this.selectedIds = []
        },
      
      /*用户查询功能*/
      search(){
          this.searchObj = {...this.tempSearchObj}
          this.getUsers()
      },
      /* 清除搜索栏 */
      resetSearch(){
          this.searchObj = {
            username: ''
          }
          this.tempSearchObj = {
            username: ''
          }
          this.getUsers()
      },

      /* 添加用户的事件*/
      showAddUser(){
          //清空修改查看时的数据
          this.user = {}
          this.dialogUserVisible = true
          // 清除校验(必须在界面更新之后)
          this.$nextTick(() => this.$refs.userForm.clearValidate())
      },
      //用户对话框取消
      cancel(){
        this.dialogUserVisible = false
        // 问题：取消时清空，对话框隐藏过程中，密码框会显示出来
        // this.user = {}
        setTimeout(()=>{
          this.user = {}
        },200)
      },

      //添加&修改用户信息的确认事件
      addOrUpdate(){
        //表单校验通过
          this.$refs.userForm.validate(valid => {
          if (valid) {
            const {user} = this
            this.loading = true
            // 语法：对象["属性名"] = 属性值
             this.$API.user[user.id ? 'update' : 'add'](user).then((result) => {
              this.loading = false
              // 弹出信息：添加品牌成功、修改品牌成功
              this.$message({
                //修改时拿到的是服务器返回的数据有id值
                       message:(user.id ?'修改用户成功':"添加用户成功"),
                       type:'success'
                    })
              // 如果添加用户：停留在第一页，修改用户应该停留在当前页面
              this.getUsers(user.id ? this.currentPage : 1)
              //退出清空数据,在点击添加按钮是也有清空操作
              this.user = {}
              this.dialogUserVisible = false
            })
          }
        })
      },

      /* 自定义密码校验*/
       validatePassWord(rule, value, callback){
        /*  使用test()方法检查字符串是否符合正则表达式的规则，
        如果符合则返回true，否则返回false */
        let  pwdFlog = /^[a-zA-Z0-9_-]{6,16}$/.test(value)
        if(!value){
          callback(new Error('密码不能为空'))
        }else if(!pwdFlog) {
            value.length < 6 ? callback('密码不能小于6位'):callback('密码格式不正确')
        }else{
          callback()
        }
      },
 /*   validatePassWord2(rule, value, callback){
        if (value === '') {
          callback(new Error('请再次输入密码'));
        } else if (value !== this.user.password) {
          callback(new Error('两次输入密码不一致!'));
        } else {
          callback();
        }
      }, */

      /* 操作模块的事件回调 */
      //分配用户角色
      async showAssignRole(curruser){
          this.user = {...curruser}
          this.dialogRoleVisible = true
          const result = await this.$API.user.getRoles(curruser.id)
          if (result.code == 20000 || result.code == 200) {
            const { allRolesList, assignRoles } = result.data
            this.allRoles = allRolesList
            this.userRoleIds = assignRoles.map(item => item.id)

            //要判断单选是否全部勾选，而改变全选框的状态
             const {allRoles,userRoleIds} = this
             this.checkAll = userRoleIds.length === allRoles.length && allRoles.length > 0
             this.isIndeterminate = userRoleIds.length > 0 && userRoleIds.length < allRoles.length
            }
      },
      // 修改用户回调
      showUpdateUser(curruser){
        //这里需要用到深拷贝,数据结构只有一层,浅拷贝也行
        // this.user = cloneDeep(curruser)   
        this.user = {...curruser}
        this.dialogUserVisible = true
          
      },
      //删除用户信息的回调
      async removeUser(userid){
            await this.$API.user.removeById(userid)
            this.$message({
              message: '删除成功',
              type: 'success'
            })
            //再次获取用户信息数据,this.users.length>1说明当前页的数据大于1,如果小于1删除后展示前面一页
            this.getUsers(this.users.length>1?this.currentPage:this.currentPage -1);
      },
     
      /*分配角色多选框的回调*/
      //全选
      handleCheckAllChange(val){// val 当前勾选状态true/false
      // 如果当前全选, userRoleIds就是所有角色id的数组, 否则是空数组
      this.userRoleIds = val ? this.allRoles.map(item => item.id) : []
      // 如果当前不是全选也不全不选时, 指定为false
      this.isIndeterminate = false
      },
      //单个多选
      handleCheckedChange(value){
        //value为选中的所有角色id的数组
        const {allRoles,userRoleIds} = this
        //要判断单选是否全部勾选，而改变全选框的状态
        this.checkAll = userRoleIds.length === allRoles.length && allRoles.length > 0 
        this.isIndeterminate = userRoleIds.length > 0 && userRoleIds.length < allRoles.length
      },
      //保存角色分配
      async SaveAssignRole(){
          const {user,userRoleIds} = this
          const userId = user.id
          //数组行不通，join() 方法将数组作为字符串返回。
          const roleId = userRoleIds.join()
          this.loading = true
          const result = await this.$API.user.assignRoles(userId,roleId)
          if(result.code == 20000 || result.code == 200){
              this.loading = false
              this.$message.success('角色分配成功')
              //重置用户角色数据
              this.resetRoleData()
              //刷新用户管理列表
              this.getUsers(this.currentPage)
              //如果配置的用户是当前用户，则重新加载当前页面
              console.log(this.$store.getters.name, this.user)
              if (this.$store.getters.name===this.user.username) {
                   window.location.reload()
               }
          }
       
      },
      //取消分配角色对话框-- 重置用户角色的数据
      resetRoleData(){
         this.dialogRoleVisible = false 
        //清除勾选的数据
         this.userRoleIds = []
         this.allRoles = []
        //全选框复位
         this.checkAll = false
         this.isIndeterminate = false
      }
   },
   //发请求一般情况下，我们都是在mounted去发，但是也可以在created内部去
   mounted() {
        this.getUsers()
  },

}
</script>

<style>
  .app-container{
     margin:10px 0px;
  }
</style>